import sys
from PyQt4 import QtGui, QtCore
from enum_classes import *
import copy

class Coordinates:
    """ X Y W H """
    def __init__(self, x, y, w, h):
        self.x=x
        self.y=y
        self.w=w
        self.h=h
    def __str__(self):
        return "(%d,%d)"%(self.w,self.h)
    def __repr__(self):
        return self.__str__()

class GuiError(Exception):
    def __init__(self, value):
        self.value = value
    def __str__(self):
        return repr(self.value)

def getColorFromCode(code):
    red = int(code[0:2],16)
    green = int(code[2:4],16)
    blue = int(code[4:6],16)
    return QtGui.QColor(red,green,blue)

def setAllPalettes(palette, mode, brush):
    palette.setBrush(QtGui.QPalette.Active, mode, brush)
    palette.setBrush(QtGui.QPalette.Inactive, mode, brush)
    palette.setBrush(QtGui.QPalette.Disabled, mode, brush)

class Box:
        
    """A GUI Box""" 
    def __init__(self, coordinates, boxtype, child_vars, child_events, vars, events, attributes, children, parent = None):
        self.coordinates = coordinates
        self.boxtype = boxtype
        self.direction = BoxDirection.NONE
        self.attributes = attributes
        self.child_vars = child_vars
        self.child_events = child_events
        self.vars = vars
        self.events = events
        self.children = children
        self.parent = parent
        #self.widget = QtGui.QWidget()

    def copy(self):
        return copy.deepcopy(self)

    def updateDicts(self,var,newvalue):
        for att in self.attributes:
            if self.attributes[att].find(var)>-1:
                self.attributes[att] = self.attributes[att].replace(var,newvalue)
        old_var_dict = self.vars
        new_var_dict = {}
        for oldvar in old_var_dict:
            newvarname = oldvar.replace(var,newvalue)
            new_var_dict[newvarname]=old_var_dict[oldvar]
        old_event_dict = self.events
        new_event_dict = {}
        for oldevent in old_event_dict:
            neweventname = oldevent.replace(var,newvalue)
            new_event_dict[neweventname]=old_event_dict[oldevent]
        for child in self.children:
            child.updateDicts(var,newvalue)
        self.vars = new_var_dict
        self.events = new_event_dict
                
    def createLoopInstance(self,var,newvalue):
        b = self.copy()
        b.updateDicts(var,newvalue)
        return b

    def __str__(self):
        if len(self.children)>0:
            return "%d:(%d,%d) (%d children)"%(self.boxtype,self.coordinates.w,self.coordinates.h, len(self.children))
        return "%d:(%d,%d)"%(self.boxtype,self.coordinates.w,self.coordinates.h)
    def __repr__(self):
        return self.__str__()

    def __getitem__(self,index):
        return self

    def __display_general__(self):
        alignval = 0
        if (self.attributes.has_key("halign")):
            halign = self.attributes["halign"]
            if halign == "left":
                alignval |= QtCore.Qt.AlignLeft
            elif halign == "right":
                alignval |= QtCore.Qt.AlignRight
            elif halign == "center":
                alignval |= QtCore.Qt.AlignHCenter
            else:
                raise GuiError('Incorrect Horizontal Alignment')
        if (self.attributes.has_key("valign")):
            valign = self.attributes["valign"]
            if valign == "top":
                alignval |= QtCore.Qt.AlignTop
            elif valign == "bottom":
                alignval |= QtCore.Qt.AlignBottom
            elif valign == "middle":
                alignval |= QtCore.Qt.AlignVCenter
            else:
                raise GuiError('Incorrect Vertical Alignment')
        if (alignval!=0):
            self.widget.setAlignment(alignval)
	if (self.attributes.has_key("scrollArea")):
	    self.parent.widget.setWidget(self.widget)
        pal = self.widget.palette()
        if(self.attributes.has_key("bgcolor")):
            self.widget.setAutoFillBackground(True)
            bgbrush = QtGui.QBrush(getColorFromCode(self.attributes["bgcolor"]))
            setAllPalettes(pal, QtGui.QPalette.Button, bgbrush);
            setAllPalettes(pal, QtGui.QPalette.Base, bgbrush);
            setAllPalettes(pal, QtGui.QPalette.Window, bgbrush);
        if(self.attributes.has_key("fgcolor")):
            fgbrush = QtGui.QBrush(getColorFromCode(self.attributes["fgcolor"]))
            setAllPalettes(pal, QtGui.QPalette.WindowText, fgbrush);
            setAllPalettes(pal, QtGui.QPalette.Text, fgbrush);
            setAllPalettes(pal, QtGui.QPalette.ButtonText, fgbrush);
        self.widget.setPalette(pal);
        if self.attributes.has_key("enabled"):
            self.widget.setEnabled(self.attributes["enabled"])

    def __display_empty__(self):
        try:
            parent = self.parent.widget
        except:
            parent = None
        self.widget = QtGui.QWidget(parent)
        c = self.coordinates
        self.widget.setGeometry(c.x, c.y, c.w, c.h)
    def __display_window__(self):
        self.widget = QtGui.QWidget()
        self.widget.resize(self.coordinates.w, self.coordinates.h);
        if (self.attributes.has_key("text")):
            self.widget.setWindowTitle(self.attributes["text"])
        else:
            self.widget.setWindowTitle("")

    def __display_splitter__(self):
        if (self.attributes.has_key("vertical")):
            vertical = self.attributes["vertical"]
        else:
            vertical = False
        if vertical:
            orientation = QtCore.Qt.Vertical
        else:
            orientation = QtCore.Qt.Horizontal
        self.widget = QtGui.QSplitter(orientation, self.parent.widget)
        c = self.coordinates
        self.widget.setGeometry(c.x, c.y, c.w, c.h)


    def __display_button__(self):
        if (self.attributes.has_key("text")):
            text = self.attributes["text"]
        else:
            text = ""
        self.widget = QtGui.QPushButton(text,self.parent.widget)
        c = self.coordinates
        self.widget.setGeometry(c.x, c.y, c.w, c.h)


    def __display_label__(self):
        if (self.attributes.has_key("text")):
            text = self.attributes["text"]
        else:
            text = ""
        self.widget = QtGui.QLabel(text,self.parent.widget)
        c = self.coordinates
        self.widget.setGeometry(c.x, c.y, c.w, c.h)

    def __display_textbox__(self):
        if (self.attributes.has_key("text")):
            text = self.attributes["text"]
        else:
            text = ""
        self.widget = QtGui.QTextEdit(text,self.parent.widget)
        c = self.coordinates
        self.widget.setGeometry(c.x, c.y, c.w, c.h)

    def __display_checkbox__(self):
        if (self.attributes.has_key("text")):
            text = self.attributes["text"]
        else:
            text = ""
        self.widget = QtGui.QCheckBox(text,self.parent.widget)
        c = self.coordinates
        self.widget.setGeometry(c.x, c.y, c.w, c.h)
        if (self.attributes.has_key("checked")):
            self.widget.setCheckState(int(self.attributes["checked"]))
        else:
            self.widget.setCheckState(False)

    def __display_radiobutton__(self):
        if (self.attributes.has_key("text")):
            text = self.attributes["text"]
        else:
            text = ""
        self.widget = QtGui.QRadioButton(text,self.parent.widget)
        c = self.coordinates
        self.widget.setGeometry(c.x, c.y, c.w, c.h)
        if (self.attributes.has_key("checked")):
            self.widget.setChecked(self.attributes["checked"])
        else:
            self.widget.setChecked(False)


    def __display_image__(self):
        c = self.coordinates
        self.widget = QtGui.QLabel(self.parent.widget)
        if (self.attributes.has_key("image")):
            pix = QtGui.QPixmap(self.attributes["image"])
            pix = pix.scaled(c.w, c.h, QtCore.Qt.IgnoreAspectRatio, QtCore.Qt.SmoothTransformation)
            self.widget.setPixmap(pix)
        self.widget.setGeometry(c.x, c.y, c.w, c.h)

    def __display_slider__(self):
        if not ((self.attributes.has_key("minvalue") and self.attributes.has_key("maxvalue"))):
            raise GuiError('Missing edge values')
        minvalue = int(self.attributes["minvalue"])
        maxvalue = int(self.attributes["maxvalue"])
        if self.attributes.has_key("value"):
            value = int(self.attributes["value"])
        else:
            value = minvalue
        self.widget = QtGui.QSlider(QtCore.Qt.Horizontal,self.parent.widget)
        self.widget.setMinimum(minvalue)
        self.widget.setMaximum(maxvalue)
        self.widget.setValue(value)
        c = self.coordinates
        self.widget.setGeometry(c.x, c.y, c.w, c.h)        
                 
    def __display_frame__(self):
        self.widget = QtGui.QFrame(self.parent.widget)
        #if (self.attributes.has_key("style")):
            #self.widget.setFrameStyle(self.attributes["style"])
        #else:
            #self.widget.setFrameStyle(QtGui.QFrame.Sunken | QtGui.QFrame.Panel)
        self.widget.setFrameStyle(QtGui.QFrame.Sunken | QtGui.QFrame.Panel)
        c = self.coordinates
        self.widget.setGeometry(QtCore.QRect(c.x, c.y, c.w, c.h))          

	
    def __display_scrollarea__(self):
        self.widget = QtGui.QScrollArea(self.parent.widget)
        c = self.coordinates
        self.widget.setGeometry(QtCore.QRect(c.x, c.y, c.w, c.h))

    def __display_combobox__(self):
        if not self.attributes.has_key("data"):
            data = []
        else:
            data = self.attributes["data"]
        self.widget = QtGui.QComboBox(self.parent.widget)
        c = self.coordinates
        self.widget.setGeometry(c.x, c.y, c.w, c.h)
        for item in data:
            self.widget.addItem(item)

    
    def prepare(self):
        if self.boxtype==BoxType.EMPTY:
            self.__display_empty__()
        elif self.boxtype==BoxType.WINDOW:
            self.__display_window__()
        elif self.boxtype==BoxType.BUTTON:
            self.__display_button__()
        elif self.boxtype==BoxType.LABEL:
            self.__display_label__()
        elif self.boxtype==BoxType.TEXTBOX:
            self.__display_textbox__()
        elif self.boxtype==BoxType.CHECKBOX:
            self.__display_checkbox__()
        elif self.boxtype==BoxType.IMAGE:
            self.__display_image__()
        elif self.boxtype==BoxType.SLIDER:
            self.__display_slider__()
        elif self.boxtype==BoxType.FRAME:
            self.__display_frame__()
        elif self.boxtype==BoxType.SCROLLAREA:
            self.__display_scrollarea__()
        elif self.boxtype==BoxType.RADIOBUTTON:
            self.__display_radiobutton__()
        elif self.boxtype==BoxType.COMBOBOX:
            self.__display_combobox__()
        elif self.boxtype==BoxType.SPLITTER:
            self.__display_splitter__()
        else:
            raise GuiError('Unsupported Type: '+str(self.boxtype))
        for b in self.children:
            b.prepare()
            #important note: the children should be in order:
            #top to bottom, or left to right.
            if self.boxtype==BoxType.SPLITTER:
                self.widget.addWidget(b.widget)
        self.__display_general__()


    def show(self):
        for child in self.children:
            child.show()
        self.widget.show()

    def setText(self,new_value):
        self.widget.setText(new_value)

    def setBGColor(self, value):
        pal = self.widget.palette()
        self.widget.setAutoFillBackground(True)
        bgbrush = QtGui.QBrush(getColorFromCode(value))
        setAllPalettes(pal, QtGui.QPalette.Button, bgbrush)
        setAllPalettes(pal, QtGui.QPalette.Base, bgbrush)
        setAllPalettes(pal, QtGui.QPalette.Window, bgbrush)
        self.widget.setPalette(pal)

    def getText(self):
        #print dir(self.widget)
        return self.widget.toPlainText()

    def isChecked(self):
        if self.boxtype==BoxType.CHECKBOX:
            return self.widget.isChecked()
        elif self.boxtype==BoxType.RADIOBUTTON:
            return self.widget.isChecked()
        else:
            return False
